/**
 * 
 */
package common.quickvalid;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.ValidationAwareSupport;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.ValueStack;

import common.quickvalid.validators.IValidator;
import common.validation.FormValidator;

/**
 * Struts 2 表单验证拦截器.
 * @author beansoft
 * 日期: 2009-12-20
 */
public abstract class AbstractValidationInterceptor implements Interceptor {

    private static final long serialVersionUID = 19800201L;

    public String intercept(ActionInvocation actionInvocation) throws Exception {
        ActionProxy proxy = actionInvocation.getProxy();
        Object action = actionInvocation.getAction();
        Method method = action.getClass().getMethod(proxy.getMethod());
        FormValidator validationAnnotation = method.getAnnotation(FormValidator.class);
        if (validationAnnotation != null) {
            String validationExpressions = validationAnnotation.value();// 验证表达式
            String input = validationAnnotation.input();
            // 验证不通过时返回指定的输入页result
            if (validationAnnotation.enabled() && parseAndValid(action, validationExpressions)) {
                return errorOutput(input);
            }
        }
        String result = actionInvocation.invoke();// Invoke the action
        return result;
    }

    /**
     * 分析并执行验证, 当验证失败时返回 true.
     * @param action Action 对象
     * @param validationExpression 验证规则表达式
     */
    protected boolean parseAndValid(Object action, String validationExpressions) {
        String[] validations = validationExpressions.split(";");
        boolean result = false;

        StringBuffer allMessages = new StringBuffer();
        ValidationAwareSupport support = null;// 使用 Struts 内置的 ValidationAwareSupport 来启用普通验证情况下的字段错误记录
        // 处理单条验证
        for (String expression : validations) {
            StringBuffer buff = new StringBuffer();
            if (expression != null && expression.length() > 0) {
                FieldExpressionParser parser = new FieldExpressionParser(expression);
                List<IValidator> validators = parser.getValidations();
                for (IValidator validator : validators) {
                    String msg = validator.doValidation(parser.getFieldName(), parser.getFieldDescription(),
                            ActionContext.getContext().getParameters(), validator.getArgs());
                    if (msg != null) {
                        // 设置单个表单域表单验证结果消息, 兼容 Struts 2
                        if (action instanceof ValidationAware) {
                            ((ValidationAware) action).addFieldError(parser.getFieldName(), msg);
                        } else {
                            if (support == null) {
                                support = new ValidationAwareSupport();
                            }
                            support.addFieldError(parser.getFieldName(), msg);// Keep error message, 2010-03-04 by BeanSoft
                        }

                        buff.append(msg + "<br>");
                        result = true;
                    }
                }
                if (buff.toString().length() > 0) {
                    // 记录下所有表单错误
                    allMessages.append(buff);
                }
            }
        }
        // 添加 Action Error 消息
        if (action instanceof ValidationAware) {
            ((ValidationAware) action).addActionError(allMessages.toString());
        } else if (support != null) {
            ServletActionContext.getRequest().setAttribute("errors", support.getFieldErrors());
        }
        //      else {// 非验证支持类则指定为固定消息
        ServletActionContext.getRequest().setAttribute("validationErrors", allMessages.toString());
        //      }
        return result;
    }

    /**
     * 获取所有字段的验证错误
     * @return
     */
    @SuppressWarnings("unchecked")
    protected Map<String, List<String>> getFieldErrors() {
        ValueStack vc = ActionContext.getContext().getValueStack();
        return (Map<String, List<String>>) vc.findValue("fieldErrors");
    }

    /**
     * 子类重写此方法实现不同的错误结果输出
     * @param input 跳转页
     * @return
     */
    protected abstract String errorOutput(String input);

    public void destroy() {
    }

    public void init() {
        //add by nassir wen 2012-07-19 初始化fieldExpressionParser静态块
        new FieldExpressionParser();
    }
}
